package com.itheima.java.ai.langchin4j.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.java.ai.langchin4j.entity.SymptomAssessment;
import com.itheima.java.ai.langchin4j.mapper.SymptomAssessmentMapper;
import com.itheima.java.ai.langchin4j.service.SymptomAssessmentService;
import dev.langchain4j.model.chat.ChatLanguageModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 症状自评服务实现类
 *
 * @author xiaozhi
 * @since 2025-01-07
 */
@Service
@RequiredArgsConstructor
public class SymptomAssessmentServiceImpl extends ServiceImpl<SymptomAssessmentMapper, SymptomAssessment> 
        implements SymptomAssessmentService {

    private static final Logger log = LoggerFactory.getLogger(SymptomAssessmentServiceImpl.class);
    private final ChatLanguageModel chatLanguageModel;
    private final SymptomAssessmentMapper symptomAssessmentMapper;

    // 高风险症状关键词
    private static final Set<String> HIGH_RISK_KEYWORDS = Set.of(
        "胸痛", "呼吸困难", "意识丧失", "昏迷", "大出血", "剧烈头痛", 
        "高热", "抽搐", "窒息", "休克", "心悸", "晕厥"
    );

    // 中风险症状关键词
    private static final Set<String> MEDIUM_RISK_KEYWORDS = Set.of(
        "发热", "咳嗽", "腹痛", "头痛", "恶心", "呕吐", "腹泻", 
        "关节痛", "肌肉痛", "失眠", "食欲不振"
    );

    // 科室推荐映射
    private static final Map<String, String> DEPARTMENT_MAPPING = Map.of(
        "心脏|胸痛|心悸|心律", "心内科",
        "头痛|头晕|神经|记忆", "神经内科",
        "腹痛|腹泻|消化|胃痛", "消化内科",
        "咳嗽|呼吸|肺部|胸闷", "呼吸内科",
        "关节|骨痛|肌肉|运动", "骨科",
        "皮肤|过敏|湿疹|瘙痒", "皮肤科",
        "眼部|视力|眼痛|眼红", "眼科",
        "耳部|听力|耳痛|耳鸣", "耳鼻喉科"
    );

    @Override
    @Transactional
    public SymptomAssessment createAssessment(SymptomAssessment assessment) {
        try {
            // 设置默认值
            assessment.setStatus("PENDING");
            assessment.setCreatedAt(LocalDateTime.now());
            assessment.setUpdatedAt(LocalDateTime.now());
            
            // AI分析症状
            String aiAnalysis = analyzeSymptoms(assessment);
            assessment.setAiAnalysis(aiAnalysis);
            
            // 计算风险等级
            String riskLevel = calculateRiskLevel(assessment);
            assessment.setRiskLevel(riskLevel);
            
            // 推荐科室
            String department = recommendDepartment(assessment.getMainSymptoms());
            assessment.setRecommendedDepartment(department);
            
            // 计算紧急程度
            Integer urgencyScore = calculateUrgencyScore(assessment);
            assessment.setUrgencyScore(urgencyScore);
            
            // 保存到数据库
            save(assessment);
            
            log.info("创建症状评估成功，用户ID: {}, 评估ID: {}", assessment.getUserId(), assessment.getId());
            return assessment;
            
        } catch (Exception e) {
            log.error("创建症状评估失败", e);
            throw new RuntimeException("创建症状评估失败: " + e.getMessage());
        }
    }

    @Override
    public String analyzeSymptoms(SymptomAssessment assessment) {
        try {
            String prompt = buildAnalysisPrompt(assessment);
            String response = chatLanguageModel.chat(prompt);
            
            log.info("AI症状分析完成，用户ID: {}", assessment.getUserId());
            return response;
            
        } catch (Exception e) {
            log.error("AI症状分析失败", e);
            return "AI分析暂时不可用，请咨询医生获取专业建议。";
        }
    }

    @Override
    public String calculateRiskLevel(SymptomAssessment assessment) {
        try {
            String symptoms = (assessment.getMainSymptoms() + " " + 
                             Optional.ofNullable(assessment.getAccompanyingSymptoms()).orElse("")).toLowerCase();
            
            // 检查高风险症状
            for (String keyword : HIGH_RISK_KEYWORDS) {
                if (symptoms.contains(keyword.toLowerCase())) {
                    return "HIGH";
                }
            }
            
            // 检查疼痛等级
            if (assessment.getPainLevel() != null && assessment.getPainLevel() >= 8) {
                return "HIGH";
            }
            
            // 检查中风险症状
            for (String keyword : MEDIUM_RISK_KEYWORDS) {
                if (symptoms.contains(keyword.toLowerCase())) {
                    return "MEDIUM";
                }
            }
            
            // 检查疼痛等级
            if (assessment.getPainLevel() != null && assessment.getPainLevel() >= 5) {
                return "MEDIUM";
            }
            
            return "LOW";
            
        } catch (Exception e) {
            log.error("计算风险等级失败", e);
            return "MEDIUM"; // 默认中等风险
        }
    }

    @Override
    public String recommendDepartment(String symptoms) {
        if (!StringUtils.hasText(symptoms)) {
            return "全科";
        }
        
        String lowerSymptoms = symptoms.toLowerCase();
        
        for (Map.Entry<String, String> entry : DEPARTMENT_MAPPING.entrySet()) {
            String pattern = entry.getKey();
            String department = entry.getValue();
            
            if (Pattern.compile(pattern).matcher(lowerSymptoms).find()) {
                return department;
            }
        }
        
        return "全科";
    }

    @Override
    public IPage<SymptomAssessment> getAssessmentsByUserId(Long userId, Integer pageNum, Integer pageSize) {
        Page<SymptomAssessment> page = new Page<>(pageNum, pageSize);
        return symptomAssessmentMapper.selectPageByUserId(page, userId);
    }

    @Override
    public List<SymptomAssessment> getRecentAssessments(Long userId, Integer limit) {
        return symptomAssessmentMapper.selectRecentByUserId(userId, limit);
    }

    @Override
    public IPage<SymptomAssessment> getPendingReviews(Integer pageNum, Integer pageSize) {
        Page<SymptomAssessment> page = new Page<>(pageNum, pageSize);
        return symptomAssessmentMapper.selectPendingReviews(page);
    }

    @Override
    @Transactional
    public Boolean reviewAssessment(Long assessmentId, Long doctorId, String review) {
        try {
            SymptomAssessment assessment = getById(assessmentId);
            if (assessment == null) {
                return false;
            }
            
            assessment.setDoctorReview(review);
            assessment.setReviewedBy(doctorId);
            assessment.setReviewedAt(LocalDateTime.now());
            assessment.setStatus("REVIEWED");
            assessment.setUpdatedAt(LocalDateTime.now());
            
            return updateById(assessment);
            
        } catch (Exception e) {
            log.error("医生审核评估失败", e);
            return false;
        }
    }

    @Override
    public Map<String, Object> getAssessmentStatistics(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        Map<String, Object> stats = new HashMap<>();
        
        try {
            // 总评估数量
            Integer totalCount = symptomAssessmentMapper.countByUserIdAndDateRange(userId, startTime, endTime);
            stats.put("totalCount", totalCount);
            
            // 风险等级分布
            List<Map<String, Object>> riskDistribution = getRiskLevelDistribution(startTime, endTime);
            stats.put("riskDistribution", riskDistribution);
            
            // 最近评估
            List<SymptomAssessment> recentAssessments = getRecentAssessments(userId, 5);
            stats.put("recentAssessments", recentAssessments);
            
        } catch (Exception e) {
            log.error("获取评估统计数据失败", e);
        }
        
        return stats;
    }

    @Override
    public List<Map<String, Object>> getRiskLevelDistribution(LocalDateTime startTime, LocalDateTime endTime) {
        return symptomAssessmentMapper.countByRiskLevelAndDateRange(startTime, endTime);
    }

    @Override
    public List<Map<String, Object>> getDepartmentRecommendationStats(LocalDateTime startTime, LocalDateTime endTime) {
        return symptomAssessmentMapper.countByDepartmentAndDateRange(startTime, endTime);
    }

    @Override
    @Transactional
    public Boolean updateAssessmentStatus(Long assessmentId, String status) {
        try {
            SymptomAssessment assessment = getById(assessmentId);
            if (assessment == null) {
                return false;
            }
            
            assessment.setStatus(status);
            assessment.setUpdatedAt(LocalDateTime.now());
            
            return updateById(assessment);
            
        } catch (Exception e) {
            log.error("更新评估状态失败", e);
            return false;
        }
    }

    @Override
    @Transactional
    public Boolean deleteAssessment(Long assessmentId, Long userId) {
        try {
            QueryWrapper<SymptomAssessment> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("id", assessmentId)
                       .eq("user_id", userId);
            
            return remove(queryWrapper);
            
        } catch (Exception e) {
            log.error("删除症状评估失败", e);
            return false;
        }
    }

    /**
     * 构建AI分析提示词
     */
    private String buildAnalysisPrompt(SymptomAssessment assessment) {
        StringBuilder prompt = new StringBuilder();
        prompt.append("请作为专业医生分析以下症状信息：\n\n");
        prompt.append("主要症状：").append(assessment.getMainSymptoms()).append("\n");
        
        if (StringUtils.hasText(assessment.getDuration())) {
            prompt.append("持续时间：").append(assessment.getDuration()).append("\n");
        }
        
        if (assessment.getPainLevel() != null) {
            prompt.append("疼痛等级：").append(assessment.getPainLevel()).append("/10\n");
        }
        
        if (StringUtils.hasText(assessment.getAccompanyingSymptoms())) {
            prompt.append("伴随症状：").append(assessment.getAccompanyingSymptoms()).append("\n");
        }
        
        if (StringUtils.hasText(assessment.getTriggerFactors())) {
            prompt.append("诱发因素：").append(assessment.getTriggerFactors()).append("\n");
        }
        
        if (StringUtils.hasText(assessment.getCurrentMedications())) {
            prompt.append("当前用药：").append(assessment.getCurrentMedications()).append("\n");
        }
        
        prompt.append("\n请提供：\n");
        prompt.append("1. 可能的诊断方向\n");
        prompt.append("2. 建议的检查项目\n");
        prompt.append("3. 注意事项和建议\n");
        prompt.append("4. 是否需要紧急就医\n\n");
        prompt.append("请用专业但易懂的语言回答，控制在300字以内。");
        
        return prompt.toString();
    }

    /**
     * 计算紧急程度评分
     */
    private Integer calculateUrgencyScore(SymptomAssessment assessment) {
        int score = 1; // 基础分数
        
        // 根据风险等级调整
        switch (assessment.getRiskLevel()) {
            case "HIGH":
                score += 3;
                break;
            case "MEDIUM":
                score += 2;
                break;
            case "LOW":
                score += 1;
                break;
        }
        
        // 根据疼痛等级调整
        if (assessment.getPainLevel() != null) {
            if (assessment.getPainLevel() >= 8) {
                score += 2;
            } else if (assessment.getPainLevel() >= 5) {
                score += 1;
            }
        }
        
        return Math.min(score, 5); // 最高5分
    }
}